package core

import (
	"context"
	"encoding/binary"
	"fmt"
	"net"
)

type Channel struct {
	config   ChannelConfig
	pushConn net.Conn
	transfer *Transfer // 转换操作
	Ready    bool
	ctx      context.Context
	cancel   context.CancelFunc
}

func (o *Channel) Init(msg Message) {
	c := G.Dispatcher.Stream
	o.pushConn, err = net.Dial("tcp", fmt.Sprintf("%s:%d", c.Host, c.Port))
	if err != nil {
		G.Log.Errorf("Can not to connect to [%s:%d]", c.Host, c.Port)
		return
	}
	G.Log.Infof("Connected to [%s:%d]", c.Host, c.Port)
	o.OnMediaData([]byte(o.config.ChannelCode))
	o.transfer = NewTransfer(o, o.config.MediaPath)
	o.Ready = true
}

func (o *Channel) Start() {
	o.ctx, o.cancel = context.WithCancel(context.Background())
	go o.transfer.Encode(o.ctx)
	o.Ready = true
}

func (o *Channel) OnMediaData(data []byte) {
	if o.pushConn == nil {
		return
	}
	dataLenBytes := make([]byte, 2)
	binary.LittleEndian.PutUint16(dataLenBytes, uint16(len(data)))
	_, err := o.pushConn.Write(dataLenBytes)
	if err != nil {
		o.OnError(err)
		return
	}
	_, err = o.pushConn.Write(data)
	if err != nil {
		o.OnError(err)
		return
	}
}

func (o *Channel) OnError(err error) {
	G.Log.Errorf("Channel[%s] Error: %v", o.config.ChannelCode, err)
	o.Stop()
}
func (o *Channel) Stop() {
	if !o.Ready {
		return
	}
	o.transfer.Close(o.cancel)
	o.pushConn.Close()
	// 释放关联的解码器和推流tcp连接，释放内存
	o.transfer = nil
	o.pushConn = nil
	// 修改就绪状态为未就绪
	o.Ready = false
}
